import { HttpClient } from "@angular/common/http";
import { Component } from "@angular/core";
import { EMPTY, Observable, Subject, fromEvent, merge } from "rxjs";
import {
  debounceTime,
  filter,
  map,
  repeat,
  startWith,
  switchMap,
  take,
  takeUntil,
} from "rxjs/operators";
import { interval5 } from "../shared-rx/time";

interface User {
  address: string;
  balance: number;
  created: string;
  email: string;
  first: string;
  last: string;
  // 手动绑定
  index: number;
}

@Component({
  selector: "pull-refresh",
  standalone: false,
  templateUrl: "./pull-refresh.component.html",
  // styleUrl: "./pr-root.component.less",
})
export class PullRefreshComponent {
  title = "pull-refresh";

  interval5$: Observable<number> = interval5;

  // click trigger
  click$: Subject<void> = new Subject<void>();

  // auto refresh
  change$: Subject<boolean> = new Subject<boolean>();

  // touch trigger
  private touchstart$: Observable<TouchEvent> = fromEvent<TouchEvent>(
    document.scrollingElement!,
    "touchstart",
  );

  private touchend$: Observable<TouchEvent> = fromEvent<TouchEvent>(
    document.scrollingElement!,
    "touchend",
  );

  private touchmove$: Observable<TouchEvent> = fromEvent<TouchEvent>(
    document.scrollingElement!,
    "touchmove",
  );

  private clickRefresh$: Observable<void> = this.click$.pipe(debounceTime(300));

  autoRefresh$: Observable<number> = this.change$.pipe(
    switchMap((enabled) => (enabled ? this.interval5$ : EMPTY)),
  );

  touchRefresh$: Observable<number> = this.touchstart$.pipe(
    switchMap((touchstart) =>
      this.touchmove$.pipe(
        map(
          (touchmove) =>
            touchmove.touches[0].pageY - touchstart.touches[0].pageY,
        ),
        takeUntil(this.touchend$),
      ),
    ),
    filter((position) => position >= 300),
    take(1),
    repeat(),
  );

  // merge Event
  private refresh$: Observable<number | boolean | void> = merge(
    this.clickRefresh$,
    this.autoRefresh$,
    this.touchRefresh$,
  ).pipe(startWith(true));

  // do fetch
  view$: Observable<User[]> = this.refresh$.pipe(switchMap(() => this.fetch$));

  constructor(private httpClient: HttpClient) {
    this.fetch$ = this.httpClient
      .get<User[]>("https://randomapi.azurewebsites.net/api/users")
      .pipe(map((users) => users.map((user, index) => ({ ...user, index }))));
  }

  /**
   * @thisFetch
   */
  fetch$: Observable<User[]>;
}
